#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <strings.h>
#include <dos.h>

#include "util.h"
#include "tracelog.h"
#include "TC1x.h"

typedef STATUS (*PTC_FUNC)( PAHCI_EXT AhciExt );
CHAR TC1_1_Desc[] = 
"Single Xfer\n\
------------------------\n\
PCIe device is expected to upstream write 256 bytes to each PcMem\n\
XferLen register should be updated to 8\n";

CHAR TC1_2_Desc[] = 
"Host Address Alignment Issue\n\
------------------------\n\
Write/Read DMA Ext. Host address is aligned to 16, 8, 4, 2 bytes.\n";
CHAR TC1_3_Desc[] = 
"2 PRDTs across 32k boundary Issue\n\
------------------------\n\
Read/Write DMA Ext. Host address is described by 2 PRDTs.\n";
CHAR TC1_4_Desc[] = 
"Huge Data Transfer Issue\n\
------------------------\n\
Read/Write DMA Ext. More than 1Mega bytes\n";
CHAR TC1_5_Desc[] = 
"1~40 PRDTs Data Transfer Issue\n\
------------------------\n\
Read/Write DMA Ext. 1~40 PRDTs\n";

CHAR TC1_6_Desc[] = 
"Host Address Alignment Issue\n\
------------------------\n\
RW DMA Ext. Host address and length are aligned to 16, 8, 4, 2 bytes.\n";
CHAR TC1_7_Desc[] = 
"NCQ RW Burst Test\n\
------------------------\n\
NCQ RW Burst 1~32 commands.\n";

CHAR TC1_8_Desc[] = 
"NCQ RW Heavy Loading Test\n\
------------------------\n\
NCQ RW Heavy Loading Test.\n";

CHAR TC1_9_Desc[] = 
"NCQ RW + Address Alignment Issue\n\
------------------------\n\
NCQ RW. Host address and length are aligned to 16, 8, 4, 2 bytes.\n";


CHAR TC1_10_Desc[] = 
"Write/Read for flash moving data\n\
------------------------\n\
1. Write LBA = 0 by 128k bytes\n\
2. Flash model moves data to LBA = 256\n\
3. Read LBA = 256, check to be sure the read and write data are the same\n";


CHAR TC1_11_Desc[] = 
"W/R the whole disk for flash moving data\n\
------------------------\n\
1. Write the whole disk (ramdisk) by 128k bytes\n\
2. In the meantime, flash model moves data to flash\n\
3. Read the whole disk (ramdisk), check to be sure the read and write data are the same\n";

typedef struct _tc_ext{
    PTC_FUNC Func;
    CHAR*    Description;
}TC_EXT;
TC_EXT TC1Table[]=
{
    { TC1_1, TC1_1_Desc },
//    { TC1_2, TC1_2_Desc },
//    { TC1_3, TC1_3_Desc },
//    { TC1_4, TC1_4_Desc },
//    { TC1_5, TC1_5_Desc },
//    { TC1_6, TC1_6_Desc },
//    { TC1_7, TC1_7_Desc },
//    { TC1_8, TC1_8_Desc },
//    { TC1_9, TC1_9_Desc },
//      { TC1_10, TC1_10_Desc },
//      { TC1_11, TC1_11_Desc },
    NULL,
};

STATUS TestCase1xEntry( PAHCI_EXT AhciExt )
{
    uint32_t address;
    STATUS ret;
    ULONG siz;
    ULONG val;
    ULONG cnt;
    PULONG ptr;
    int i;


    // ------- The end of initialization for AHCI Port 0 -----
    ret = SUCCESS;
    cnt = 0;
    while( TC1Table[ cnt ].Func )
    {
        LogMsg( COMP_INIT, DBG_NORMAL, "TC1: No.%d Test Case\n%s", cnt, TC1Table[ cnt ].Description );
        ret = TC1Table[ cnt ].Func( AhciExt );
        if ( ret != SUCCESS )
        {
            LogMsg( COMP_INIT, DBG_NORMAL, "Failed with %s\n", StatusToString( ret ) );
            break;
        }else{
            LogMsg( COMP_INIT, DBG_NORMAL, "----- SUCCESS -----\n\n" );
        }
        cnt++;
    }
    return ret;
}

STATUS TC1_1( PAHCI_EXT AhciExt )
{
    ULONG value;
    ULONG siz;
    ULONG address;
    STATUS ret;
    int i;

    siz = PC_MEM_LENGTH * PC_MEM_NUM;
    /* setup Xilinx PCIe register */

    LogMsg( COMP_SCRIPT, DBG_NORMAL, "Allocate Memory and Set PC_MEM_ADDR register\n");
    address = DpmiMapPhysMemory( PC_MEM_BA, siz );
    if ( address == NULL )
    {
        LogMsg( COMP_INIT, DBG_ERROR, "Failed to map physical memory for %08X @ %08X bytes!\n", siz, address );
        ret = ALLOCATE_MEM_FAILED;
        return ret;
    }else{
        memset( (void*)address, 0, siz );
        for( i = 0; i < PC_MEM_NUM; i++)
        {
        *( (ULONG*)AhciExt->PcMemArray[ i ] )  = address + PC_MEM_LENGTH * i;
        }
    }
    for( i = 0; i < PC_MEM_NUM; i++)
    {
        LogMsg( COMP_SCRIPT, DBG_NORMAL, "[%d] PC memory address: %08X\n", i, *(AhciExt->PcMemArray[ i ] ) );
    }

    ret = SUCCESS;
    value= 0x00000002;
    LogMsg( COMP_SCRIPT, DBG_NORMAL, "Wr CmdReg : %08X\n", value);
    //*(PULONG)( AhciExt->CmdRegAddr ) = 0x00000002;

    LogMsg( COMP_SCRIPT, DBG_NORMAL, "Wait for 1 second ...\n");
    sleep( 1 );

    //value = *( (PULONG)(AhciExt->XferLenRegAddr ) );
    LogMsg( COMP_SCRIPT, DBG_NORMAL, "Transfer  : %8d Upstream MWr32 (128B)\n", value );
    LogMsg( COMP_SCRIPT, DBG_NORMAL, "Received Data @ %08X\n", AhciExt->PcMemArray[ 0 ] );

    //LogDumpData( COMP_SCRIPT, DBG_NORMAL, "First 32 bytes", (PUCHAR)AhciExt->PcMemArray[ 0 ], 32 );
//    LogDumpData( COMP_SCRIPT, DBG_NORMAL, "last  32 bytes", (PUCHAR)(AhciExt->PcMemArray[ 0 ] + 512 - 32), 32 );


    DpmiUnMapPhysMemory( address );

    return SUCCESS;
}



